package com.yuw.producerandconsumer2;

public class WarehouseStack {

	// 属性
	// 栈对象
	private Product[] whStack;
	// 栈顶位置:size表示栈中的元素个数，也就是栈顶的位置，初始位置为0
	private int size = 0;

	// 栈的容量大小
	private int capacity;

	public WarehouseStack(int capacity) {
		this.capacity = capacity;
		init();
	}

	public WarehouseStack() {
		init();
	}

	// 行为
	/**
	 * 入栈操作
	 * 
	 * @param obj 入栈的对象
	 */
	public void push(Product obj) {

		// 同步语句块（被加锁对象是仓库）
		synchronized (this) {
			// 判断仓库栈是否满，如果满了则等待消费者消费产品
			// 栈顶位置size大于栈容量，说明栈满
			if (size == capacity) {
				try {
					System.out.println("仓库满，生产者进入仓库的等待队列，等待消费者消费之后将其唤醒");
					// 让当前生产者等待消费者消费
					this.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			// 入栈
			whStack[size] = obj;
			// 栈顶位置向上移动1位
			size++;
			// 生产了产品之后，通知消费者可以消费了

			this.notifyAll();
		}
	}

	/**
	 * 出栈操作
	 * 
	 * @return 栈顶元素
	 */
	public Product pop() {
		// 取出栈顶元素对象
		Product obj = null;
		// 同步语句块（被加锁对象是仓库）
		synchronized (this) {
			// 消费者消费时，判定仓库栈是否为空
			// 如果仓库为空，则当前消费者等待生产生产
			if (size == 0) {
				try {
					System.out.println("仓库空，消费者进入仓库的等待队列，等待生产者生产之后将其唤醒");
					this.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			// 栈顶元素指针向下挪动一个位置
			size--;
			// 取出栈顶元素对象
			obj = whStack[size];

			// 消费者消费了产品，仓库不为空了，则通知生产者可以生产放入产品了
			this.notifyAll();
		}
		// 返回栈顶元素
		return obj;
	}

	/**
	 * 栈初始化，默认长度为10
	 */
	private void init() {
		if (capacity == 0) {
			capacity = 10;
		}
		// 初始化栈对象
		whStack = new Product[capacity];
	}

	public Product[] getWhStack() {
		return whStack;
	}

	public void setWhStack(Product[] whStack) {
		this.whStack = whStack;
	}

	public int getSize() {
		return size;
	}

	public void setSize(int size) {
		this.size = size;
	}

	public int getCapacity() {
		return capacity;
	}

	public void setCapacity(int capacity) {
		this.capacity = capacity;
	}

}